package com.kw.rabbittest.deadletter;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class BusinessMessageSender implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMsg(String msg){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(UUID.randomUUID().toString());
        rabbitTemplate.convertSendAndReceive(RabbitMQConfig.BUSINESS_EXCHANGE_NAME,RabbitMQConfig.BUSINESS_QUEUEA_NAME , msg,correlationData);
    }


    // 如果发送到交换器都没有成功（比如说删除了交换器），ack 返回值为 false
    // 如果发送到交换器成功，但是没有匹配的队列（比如说取消了绑定），ack 返回值为还是 true （这是一个坑，需要注意）
    //如何模拟 ack 返回值为 false，先把项目启动，然后再把交换器删除，就会发现 ConfirmCallback 的 ack 为 false。
    //1、 ConfirmCallback确认模式
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

        String msgId = correlationData.getId();//用这个id来定位具体消息
        if(ack){
            System.out.println("消息成功发送到broker");
            System.out.println("消息标识是:" + msgId);
        }else {
            System.out.println("消息被拒收的原因是:" + cause);
        }

    }
    //2、 ReturnCallback 退回模式
    // 设置 ReturnCallback 回调
    // 如果发送到交换器成功，但是没有匹配的队列，就会触发这个回调
    //如何模拟 发送到交换器成功，但是没有匹配的队列，先把项目启动，然后再把队列解绑，再发送消息，就会触发 ReturnCallback 回调，而且发现消息也丢失了，没有到任何队列。
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("消息被退回");
        System.out.println("被退回的消息是 :" + new String(message.getBody()));
        System.out.println("被退回的消息编码是 :" + replyCode);
    }
}